import {
  AfterViewInit,
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  HostBinding,
  OnInit,
  ViewChild,
} from '@angular/core';
import { LayoutConfigService } from './core/services/layout-config.service';
import { ClassInitService } from './core/services/class-init.service';
import { TranslationService } from './core/services/translation.service';
import * as objectPath from 'object-path';
import { DomSanitizer } from '@angular/platform-browser';
import { NavigationEnd, Router, RoutesRecognized, CanActivate, ActivatedRoute } from '@angular/router';
import { PageConfigService } from './core/services/page-config.service';
import { filter } from 'rxjs/operators';
import { SplashScreenService } from './core/services/splash-screen.service';
// language list
import { locale as chLang } from './config/i18n/ch';
import { LicenseGuard } from './core/services/LicenseGuard.service';
import { ProfileService } from './services/profile.service';

// LIST KNOWN ISSUES
// [Violation] Added non-passive event listener; https://github.com/angular/angular/issues/8866

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'body[m-root]',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements AfterViewInit, OnInit {
  title = 'Metronic';

  @HostBinding('style') style: any;
  @HostBinding('class') classes: any = '';

  @ViewChild('splashScreen', { read: ElementRef })
  splashScreen: ElementRef;
  splashScreenImage: string;
  profile$ = this.profileService.profile$;

  constructor(
    private layoutConfigService: LayoutConfigService,
    private classInitService: ClassInitService,
    private sanitizer: DomSanitizer,
    private translationService: TranslationService,
    private router: Router,
    private pageConfigService: PageConfigService,
    private splashScreenService: SplashScreenService,
    private licenseGuard: LicenseGuard,
    private route: ActivatedRoute,
    private profileService: ProfileService,

  ) {
    // subscribe to class update event
    this.classInitService.onClassesUpdated$.subscribe(classes => {
      // get body class array, join as string classes and pass to host binding class
      setTimeout(() => (this.classes = classes.body.join(' ')));
    });

    this.layoutConfigService.onLayoutConfigUpdated$.subscribe(model => {
      this.classInitService.setConfig(model);

      this.style = '';
      if (objectPath.get(model.config, 'self.layout') === 'boxed') {
        const backgroundImage = objectPath.get(model.config, 'self.background');
        if (backgroundImage) {
          this.style = this.sanitizer.bypassSecurityTrustStyle(
            'background-image: url(' + objectPath.get(model.config, 'self.background') + ')',
          );
        }
      }

      // splash screen image
      this.splashScreenImage = objectPath.get(model.config, 'loader.image');
    });

    // register translations
    this.translationService.loadTranslations(chLang);

    // override config by router change from pages config
    this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(event => {
      this.layoutConfigService.setModel(
        { page: objectPath.get(this.pageConfigService.getCurrentPageConfig(), 'config') },
        true,
      );
    });
  }

  ngOnInit(): void {
    this.router.events
    .subscribe(event => {
      if (event instanceof RoutesRecognized) {
        this.guardRoute(event);
      }
    });
    this.profile$.then(profile => {
      document.title = profile.name;
    })
  }

  private guardRoute(event: RoutesRecognized): void {
    if (this.isPublic(event)) {
      return;
    }
    if (!this.callCanActivate(event, this.licenseGuard)) {
      return;
    }
  }

  private callCanActivate(event: RoutesRecognized, guard: CanActivate) {
    return guard.canActivate(this.route.snapshot, event.state);
  }
  
  private isPublic(event: RoutesRecognized) {
    return event.url === '/login';
  }

  ngAfterViewInit(): void {
    if (this.splashScreen) {
      this.splashScreenService.init(this.splashScreen.nativeElement);
    }
  }
}
